#ifndef LIB_H
#define LIB_H

#include <string>
#include <fstream>
#include <iomanip>
#include <vector>
#include <sstream>
#include <algorithm>
#include "debugstreams.h"
#include "ListeSorts.h"
using namespace std;

const unsigned int npos(string("a").find("b"));

/** @addtogroup Utilitaires
 *  @{
 */

/**
 * Gestion des compétences non martiales disponibles pour une classe donnée.
 */
enum TypeClasse
{
  Toutes, /**< Accessible à toutes les classes */
  Combattants, /**< Pour les guerriers, paladins et rôdeurs*/
  Magiciens, /**< Pour les mages et spécialistes*/
  Pretres, /**< Pour les clercs et druides*/
  Roublards /**< Pour les bardes et voleurs*/
};

/**
 * Gestion des capacités raciales.
 */
struct ListCapa
{
  string Capa;       /**< Nom de la capacité raciale */
  unsigned int Cout; /**< Cout de la capacité en PP*/
};

/**
 * Gestion des compétences de classe
 */
struct ListComp
{
  string Comp;       /**< Nom de la compétence */
  unsigned int Cout; /**< Cout de la compétence en PP */
  bool Pourcentage;  /**< Associé à un pourcentage ? */
};

/**
 * Gestion des compétences non-martiales
 */
struct ListNonMart
{
  string Comp;          /**< Nom de la compétence non-martiale */
  unsigned int Cout;    /**< Cout de la compétence */
  unsigned int Valeur;  /**< Valeur de base */
  unsigned int Trait1;  /**< Trait associé 1 */
  unsigned int Trait2;  /**< Trait associé 2 */
  TypeClasse Cl_Admise; /**< Classe autorisée */
};

/** @} */

/**
 * Gestion des sorts de mage.
 */
class Sort
{
 public:
  /**
   * Constructeur par défaut.
   * @param ecole numéro de l'école de magie
   * @param niveau niveau du sort
   * @param numero numéro du sort
   */
  Sort(const unsigned int& ecole = 0, const unsigned int& niveau = 1,
       const unsigned int& numero = 0);
  /**
   * Constructeur de copie
   * @param m_sort sort à copier
   */
  Sort(const Sort& m_sort);
  /**
   * Destructeur, ne fais rien.
   */
  ~Sort();
  /**
   * Opérateurs de comparaison "<", nécessaire pour le tri.
   * @param m_sort sort à comparer
   * @return valeur du test
   */
  bool operator<(const Sort& m_sort) const;
  /**
   * Opérateurs de comparaison ">", nécessaire pour le tri.
   * @param m_sort sort à comparer
   * @return valeur du test
   */
  bool operator>(const Sort& m_sort) const;
  /**
   * Opérateurs d'égalité "<", nécessaire pour le tri.
   * @param m_sort sort à comparer
   * @return valeur du test
   */
  bool operator==(const Sort& m_sort) const;
  /**
   * Retourne le numéro de l'école
   * @ return Ecole
   */
  unsigned int get_Ecole() const;
  /**
   * Retourne le niveau du sort
   * @ return Niveau
   */
  unsigned int get_Niveau() const;
  /**
   * Retourne le numéro du sort
   * @ return Numero
   */
  unsigned int get_Numero() const;
  /**
   * Permet d'effectuer un affichage simple d'un sort.
   * @param out le flux de sortie désiré (cout, info(), ...)
   * @param m_sort le sort à afficher
   * @return out
   */
  friend ostream& operator<<(ostream& out, const Sort& m_sort);
 protected:
  /**
   * Ecole, niveau et numéro du sort.
   */
  unsigned int Ecole, Niveau, Numero;
 private:
};

int puissance(int a, unsigned int b);

unsigned int digit(const int& a, const int& b);

string write_int(const unsigned int& nbr);

unsigned int demander_unsigned(const string& question);

unsigned int demander_unsigned_borne(const string& question,
				     const unsigned int& min,
				     const unsigned int& max);
string affiche_accent(const string& brut);

unsigned int affiche_sorts(const unsigned int& ecole,
			   const unsigned int& niveau);

bool safe_push_back(vector<unsigned int> *ptr, const unsigned int& valeur);

bool safe_push_back(vector<unsigned int> *ptr, const unsigned int& valeur,
		    vector<unsigned int>& sauter);

void gerer_espaces_blancs(char* tab[], int& nbr, vector<string>& retour);

#endif
